/**
 * 
 */
package tests;

import static org.junit.Assert.*;

import java.util.LinkedList;
import java.util.Random;
import java.util.UUID;

import org.junit.BeforeClass;
import org.junit.Test;

import sourceFiles.SupervisorStation;

import Exceptions.InvalidAgeParam;
import Exceptions.InvalidCapacity;
import Exceptions.InvalidHeightParam;
import Exceptions.InvalidRideId;
import Exceptions.InvalidRideName;
import Exceptions.XMLRidesParserException;
import Exceptions.CentralComputerExceptions.RideIDDoesntExist;
import Stubs.CentralComputerStub3;

/**
 * This test class is a unit test for the class SupervisorStation
 * 
 * @author LASO-Team
 * 
 */
public class SupervisorStationTest {
	// static parameters used in the test a defined here

	static private final int RANDOM_TEST_SIZE = 7;
	static private final int[] EDGE_OF_LEGAL_INT_VALUES = { 1, 2 };
	static private final int[] EDGE_OF_ILLEGAL_INT_VALUES = { -1, 0 };
	static private final int TEST_SIZE = RANDOM_TEST_SIZE
			+ EDGE_OF_LEGAL_INT_VALUES.length;
	static private final int MAX_RANDOM = Integer.MAX_VALUE;
	static private String[] legalRideNames;
	static private int[] legalMaxCapacities;
	static private int[] legalMinAges;
	static private int[] legalMinHeights;
	static private int[] legalRideIDs;
	static private boolean[] isExtremeRides;
	static private int[] illegalMaxCapacities;
	static private int[] illegalMinAges;
	static private int[] illegalMinHeights;
	static private int[] illegalRideIDs;
	static private int[] nonExistingLegalRideIDs;
	// end static parameters

	/**
	 * Initiating all the static arrays above with test values, as well as
	 * random parameters (number of tests, TEST_SIZE, is determined by the
	 * number of test values as well as the number of random values
	 * 
	 * @throws Exception
	 */
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		assertTrue(EDGE_OF_LEGAL_INT_VALUES.length == EDGE_OF_ILLEGAL_INT_VALUES.length);

		LinkedList<Integer> legalMaxCapacitiesList = new LinkedList<Integer>();
		LinkedList<Integer> legalMinAgesList = new LinkedList<Integer>();
		LinkedList<Integer> legalMinHeightsList = new LinkedList<Integer>();
		LinkedList<Integer> legalRideIDsList = new LinkedList<Integer>();

		LinkedList<Integer> illegalMaxCapacitiesList = new LinkedList<Integer>();
		LinkedList<Integer> illegalMinAgesList = new LinkedList<Integer>();
		LinkedList<Integer> illegalMinHeightsList = new LinkedList<Integer>();
		LinkedList<Integer> illegalRideIDsList = new LinkedList<Integer>();

		LinkedList<Integer> nonExistinglegalRideIDsListList = new LinkedList<Integer>();

		int numOfEdgeTests = EDGE_OF_LEGAL_INT_VALUES.length;
		for (int i = 0; i < numOfEdgeTests; i++) { // init the legal value first
			legalMaxCapacitiesList.add(EDGE_OF_LEGAL_INT_VALUES[i]);
			legalMinAgesList.add(EDGE_OF_LEGAL_INT_VALUES[i]);
			legalMinHeightsList.add(EDGE_OF_LEGAL_INT_VALUES[i]);
			legalRideIDsList.add(EDGE_OF_LEGAL_INT_VALUES[i]);
			illegalMaxCapacitiesList.add(EDGE_OF_ILLEGAL_INT_VALUES[i]);
			illegalMinAgesList.add(EDGE_OF_ILLEGAL_INT_VALUES[i]);
			illegalMinHeightsList.add(EDGE_OF_ILLEGAL_INT_VALUES[i]);
			illegalRideIDsList.add(EDGE_OF_ILLEGAL_INT_VALUES[i]);
		}
		Random rand = new Random();
		int newRandID;
		for (int i = 0; i < RANDOM_TEST_SIZE; i++) {

			newRandID = rand.nextInt(MAX_RANDOM) + 1;
			while (legalRideIDsList.contains(newRandID)) {
				newRandID = rand.nextInt(MAX_RANDOM) + 1;
			}

			legalMaxCapacitiesList.add(rand.nextInt(MAX_RANDOM) + 1);
			legalMinAgesList.add(rand.nextInt(MAX_RANDOM) + 1);
			legalMinHeightsList.add(rand.nextInt(MAX_RANDOM) + 1);
			legalRideIDsList.add(newRandID);

			illegalMaxCapacitiesList.add(-rand.nextInt(MAX_RANDOM));
			illegalMinAgesList.add(-rand.nextInt(Integer.MAX_VALUE));
			illegalMinHeightsList.add(-rand.nextInt(Integer.MAX_VALUE));
			illegalRideIDsList.add(-rand.nextInt(Integer.MAX_VALUE));

		}

		// add legal ride IDs that will not be created
		for (int i = 0; i < TEST_SIZE; i++) {
			newRandID = rand.nextInt(MAX_RANDOM) + 1;
			while (legalRideIDsList.contains(newRandID)) {
				newRandID = rand.nextInt(MAX_RANDOM) + 1;
			}
			nonExistinglegalRideIDsListList.add(newRandID);
		}

		assertTrue(legalRideIDsList.size() == TEST_SIZE);

		legalRideNames = new String[TEST_SIZE];
		legalMaxCapacities = new int[TEST_SIZE];
		legalMinAges = new int[TEST_SIZE];
		legalMinHeights = new int[TEST_SIZE];
		legalRideIDs = new int[TEST_SIZE];
		isExtremeRides = new boolean[TEST_SIZE];
		illegalMaxCapacities = new int[TEST_SIZE];
		illegalMinAges = new int[TEST_SIZE];
		illegalMinHeights = new int[TEST_SIZE];
		illegalRideIDs = new int[TEST_SIZE];
		nonExistingLegalRideIDs = new int[TEST_SIZE];
		for (int i = 0; i < TEST_SIZE; i++) {
			legalRideNames[i] = UUID.randomUUID().toString();
			legalMaxCapacities[i] = legalMaxCapacitiesList.get(i);
			legalMinAges[i] = legalMinAgesList.get(i);
			legalMinHeights[i] = legalMinHeightsList.get(i);
			legalRideIDs[i] = legalRideIDsList.get(i);
			isExtremeRides[i] = rand.nextBoolean();

			illegalMaxCapacities[i] = illegalMaxCapacitiesList.get(i);
			illegalMinAges[i] = illegalMinAgesList.get(i);
			illegalMinHeights[i] = illegalMinHeightsList.get(i);
			illegalRideIDs[i] = illegalRideIDsList.get(i);

			nonExistingLegalRideIDs[i] = nonExistinglegalRideIDsListList.get(i);
		}
		return;
	}

	/**
	 * this method tests that we can only enter a name that is not null.
	 * 
	 * @throws XMLRidesParserException
	 * @throws InvalidHeightParam
	 * @throws InvalidAgeParam
	 * @throws InvalidCapacity
	 */
	@Test
	public void testCreateNewRide1() throws InvalidCapacity, InvalidAgeParam,
			InvalidHeightParam, XMLRidesParserException {
		SupervisorStation supervisor = new SupervisorStation(
				new CentralComputerStub3());
		try {
			supervisor.createNewRide(null, isExtremeRides[0],
					legalMaxCapacities[0], legalMinAges[0], legalMinHeights[0]);
			fail("tried to create with a null pointer as a name string");
		} catch (InvalidRideName e) {
		}
	}

	/**
	 * This method tests that we cannot enter an invalid capacity.
	 * 
	 * @throws XMLRidesParserException
	 * @throws InvalidHeightParam
	 * @throws InvalidAgeParam
	 * @throws InvalidRideName
	 */
	@Test
	public void testCreateNewRide2() throws InvalidRideName, InvalidAgeParam,
			InvalidHeightParam, XMLRidesParserException {
		SupervisorStation supervisor = new SupervisorStation(
				new CentralComputerStub3());
		for (int i = 0; i < TEST_SIZE; i++) {
			try {
				supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
						illegalMaxCapacities[i], legalMinAges[i],
						legalMinHeights[i]);
				System.out.println(legalRideNames[i]);
				System.out.println(isExtremeRides[i]);
				System.out.println(illegalMaxCapacities[i]);
				System.out.println(legalMinAges[i]);
				System.out.println(legalMinHeights[i]);
				fail("tried to create a new ride with an illegalMaxCapacity["
						+ i + " = " + illegalMaxCapacities[i]);
			} catch (InvalidCapacity e) {
			}
		}

	}

	/**
	 * This method tests that we cannot enter an invalid age.
	 * 
	 * @throws XMLRidesParserException
	 * @throws InvalidHeightParam
	 * @throws InvalidCapacity
	 * @throws InvalidRideName
	 */
	@Test
	public void testCreateNewRide3() throws InvalidRideName, InvalidCapacity,
			InvalidHeightParam, XMLRidesParserException {
		SupervisorStation supervisor = new SupervisorStation(
				new CentralComputerStub3());
		for (int i = 0; i < TEST_SIZE; i++) {
			try {
				supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
						legalMaxCapacities[i], illegalMinAges[i],
						legalMinHeights[i]);
				fail("tried to create a new ride with an illegalMinAge[" + i
						+ " = " + illegalMinAges[i]);
			} catch (InvalidAgeParam e) {
			}
		}
	}

	/**
	 * This method tests that we cannot enter an invalid height.
	 * 
	 * @throws XMLRidesParserException
	 * @throws InvalidAgeParam
	 * @throws InvalidCapacity
	 * @throws InvalidRideName
	 */
	@Test
	public void testCreateNewRide4() throws InvalidRideName, InvalidCapacity,
			InvalidAgeParam, XMLRidesParserException {
		SupervisorStation supervisor = new SupervisorStation(
				new CentralComputerStub3());
		for (int i = 0; i < TEST_SIZE; i++) {
			try {
				supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
						legalMaxCapacities[i], legalMinAges[i],
						illegalMinHeights[i]);
				fail("tried to create a new ride with an illegalMinHeight[" + i
						+ " = " + illegalMinHeights[i]);
			} catch (InvalidHeightParam e) {
			}
		}
	}

	/**
	 * This method tests that we can create a ride with legal parameters.
	 */
	@Test
	public void testCreateNewRide5() throws Exception {
		CentralComputerStub3 ccStub = new CentralComputerStub3();
		SupervisorStation supervisor = new SupervisorStation(ccStub);
		for (int i = 0; i < TEST_SIZE; i++) {
			supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
					legalMaxCapacities[i], legalMinAges[i], legalMinHeights[i]);
		}
		LinkedList<Integer> maxCapacityList, minAgeList, minHeightList, rideIDList;
		LinkedList<String> rideNameList;
		LinkedList<Boolean> isExtremeList;
		maxCapacityList = ccStub.getMaxCapacityList();
		minAgeList = ccStub.getMinAgeList();
		minHeightList = ccStub.getMinHeightList();
		rideIDList = ccStub.getRideIDList();
		rideNameList = ccStub.getRideNameList();
		isExtremeList = ccStub.getIsExtremeRideList();
		for (int i = 0; i < TEST_SIZE; i++) {
			assertTrue(maxCapacityList.get(i) == legalMaxCapacities[i]);
			assertTrue(minAgeList.get(i) == legalMinAges[i]);
			assertTrue(minHeightList.get(i) == legalMinHeights[i]);
			assertTrue(rideNameList.get(i) == legalRideNames[i]);
			assertTrue(isExtremeList.get(i) == isExtremeRides[i]);
			assertTrue(rideIDList.get(i) == i + 1);
		}
	}


	 /**
	 * this method tests that we cannot edit a ride with ID smaller than 1.
	 */
	@Test
	public void testEditRideParams1() throws InvalidRideName, InvalidCapacity,
			InvalidAgeParam, InvalidHeightParam, XMLRidesParserException, RideIDDoesntExist {
		CentralComputerStub3 ccStub = new CentralComputerStub3();
		SupervisorStation supervisor = new SupervisorStation(ccStub);
		for (int i = 0; i < TEST_SIZE; i++) {
			try {
				supervisor.editRideParams(illegalRideIDs[i],
						legalMaxCapacities[i], legalMinAges[i],
						legalMinHeights[i]);
				fail("tried to update a ride with illegalRideIDs[" + i + "] = "
						+ illegalRideIDs[i]);
			} catch (InvalidRideId e) {
			}
		}
	}

	
	 /**
	 * this method tests that we cannot edit a ride with capacity smaller than
	 * 1.
	 * @throws InvalidCapacity 
	 * @throws InvalidRideName 
	 */
	@Test
	public void testEditRideParams2() throws InvalidRideId, InvalidAgeParam,
			InvalidHeightParam, RideIDDoesntExist, XMLRidesParserException, InvalidRideName, InvalidCapacity {
		CentralComputerStub3 ccStub = new CentralComputerStub3();
		SupervisorStation supervisor = new SupervisorStation(ccStub);
		for (int i = 0; i < TEST_SIZE; i++) {
			supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
					legalMaxCapacities[i], legalMinAges[i], legalMinHeights[i]);
		}
		for (int i = 0; i < TEST_SIZE; i++) {
			try {
				supervisor.editRideParams(ccStub.getRideIDList().get(i),
						illegalMaxCapacities[i], legalMinAges[i],
						legalMinHeights[i]);
				fail("tried to update a ride with illegalMaxCapacities[" + i
						+ "] = " + illegalMaxCapacities[i]);
			} catch (InvalidCapacity e) {
			}
		}
	}

	
	 /**
	 * this method tests that we cannot edit a ride with minimal age smaller
	 * than 1.
	 * @throws InvalidAgeParam 
	 * @throws InvalidRideName 
	 */
	@Test
	public void testEditRideParams3() throws InvalidRideId, InvalidCapacity,
			InvalidHeightParam, RideIDDoesntExist, XMLRidesParserException, InvalidRideName, InvalidAgeParam {
		CentralComputerStub3 ccStub = new CentralComputerStub3();
		SupervisorStation supervisor = new SupervisorStation(ccStub);
		for (int i = 0; i < TEST_SIZE; i++) {
			supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
					legalMaxCapacities[i], legalMinAges[i], legalMinHeights[i]);
		}
		for (int i = 0; i < TEST_SIZE; i++) {
			try {
				supervisor.editRideParams(ccStub.getRideIDList().get(i),
						legalMaxCapacities[i], illegalMinAges[i],
						legalMinHeights[i]);
				fail("tried to update a ride with illegalMinAges[" + i + "] = "
						+ illegalMinAges[i]);
			} catch (InvalidAgeParam e) {
			}
		}
	}

	 /**
	 * this method tests that we cannot edit a ride with minimal height
	 smaller
	 * than 1.
	 * @throws InvalidHeightParam 
	 * @throws InvalidRideName 
	 */
	@Test
	public void testEditRideParams4() throws InvalidRideId, InvalidCapacity,
			InvalidAgeParam, RideIDDoesntExist, XMLRidesParserException, InvalidRideName, InvalidHeightParam {
		CentralComputerStub3 ccStub = new CentralComputerStub3();
		SupervisorStation supervisor = new SupervisorStation(ccStub);
		for (int i = 0; i < TEST_SIZE; i++) {
			supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
					legalMaxCapacities[i], legalMinAges[i], legalMinHeights[i]);
		}
		for (int i = 0; i < TEST_SIZE; i++) {
			try {
				supervisor.editRideParams(ccStub.getRideIDList().get(i),
						legalMaxCapacities[i], legalMinAges[i],
						illegalMinHeights[i]);
				fail("tried to update a ride with illegalMinHeights[" + i
						+ "] = " + illegalMinHeights[i]);
			} catch (InvalidHeightParam e) {
			}
		}
	}

	
	 /**
	 * this method tests that we cannot edit a ride which does not exist.
	 */
	@Test
	public void testEditRideParams5() throws InvalidRideName, InvalidCapacity,
			InvalidAgeParam, InvalidHeightParam, XMLRidesParserException,
			InvalidRideId, RideIDDoesntExist {
		CentralComputerStub3 ccStub = new CentralComputerStub3();
		SupervisorStation supervisor = new SupervisorStation(ccStub);
		for (int i = 0; i < TEST_SIZE; i++) {
			supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
					legalMaxCapacities[i], legalMinAges[i], legalMinHeights[i]);
		}
		for (int i = 0; i < TEST_SIZE; i++) {
			try {
				supervisor.editRideParams(nonExistingLegalRideIDs[i],
						legalMaxCapacities[i], legalMinAges[i],
						legalMinHeights[i]);
				fail("tried to update a ride with nonExistingLegalRideIDs[" + i
						+ "] = " + nonExistingLegalRideIDs[i]);
			} catch (RideIDDoesntExist e) {
			}
		}
	}

	
	 /**
	 * this method tests that we can edit a ride with valid parameters.
	 */
	 @Test
	public void testEditRideParams6() throws Exception {
		CentralComputerStub3 ccStub = new CentralComputerStub3();
		SupervisorStation supervisor = new SupervisorStation(ccStub);
		for (int i = 0; i < TEST_SIZE; i++) {
			supervisor.createNewRide(legalRideNames[i], isExtremeRides[i],
					legalMaxCapacities[i], legalMinAges[i], legalMinHeights[i]);
		}
		for (int i = 0; i < TEST_SIZE; i++) {
			supervisor.editRideParams(ccStub.getRideIDList().get(i),
					legalMaxCapacities[TEST_SIZE - (i+1)], legalMinAges[TEST_SIZE
							- (i+1)], legalMinHeights[TEST_SIZE - (i+1)]);
		}

		for (int i = 0; i < TEST_SIZE; i++) {
			assertTrue(ccStub.getMaxCapacityList().get(i).equals(legalMaxCapacities[TEST_SIZE - (i+1)]));
			assertTrue(ccStub.getMinAgeList().get(i).equals(legalMinAges[TEST_SIZE - (i+1)]));
			assertTrue(ccStub.getMinHeightList().get(i).equals(legalMinHeights[TEST_SIZE - (i+1)]));
//			assertTrue(ccStub.getRideNameList().get(i).equals(legalRideNames[i]));
//			assertTrue(ccStub.getIsExtremeRideList().get(i).equals(isExtremeRides[i]));
			assertTrue(ccStub.getRideIDList().get(i) == i + 1);
		}
	}

}
